package com.mxgraph.examples;

import handler.Column;
import handler.DrawTable;
import handler.GraphXMLHandler;
import handler.TableEntity;

import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JLabel;

import com.mxgraph.io.mxCodec;
import com.mxgraph.layout.mxCircleLayout;
import com.mxgraph.layout.mxCompactTreeLayout;
import com.mxgraph.layout.mxEdgeLabelLayout;
import com.mxgraph.layout.mxFastOrganicLayout;
import com.mxgraph.layout.mxIGraphLayout;
import com.mxgraph.layout.mxOrganicLayout;
import com.mxgraph.layout.mxParallelEdgeLayout;
import com.mxgraph.layout.mxPartitionLayout;
import com.mxgraph.layout.mxStackLayout;
import com.mxgraph.layout.hierarchical.mxHierarchicalLayout;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.util.mxMorphing;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource.mxIEventListener;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.util.mxXmlUtils;
import com.mxgraph.view.mxGraph;

public class HelloWorld  {
	public String xml = "";

	final int PORT_DIAMETER = 20;
	

	int lineGap = 10;

	final int PORT_RADIUS = PORT_DIAMETER / 2;

	/**
	 * 
	 */
	private static final long serialVersionUID = -2707712944901661771L;

	private String tablexml = "&lt;table cellpadding=&quot;5&quot; style=&quot;font-size:9pt;border:none;border-collapse:collapse;width:100%;&quot;&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; style=&quot;border:1px solid gray;background:#e4e4e4;&quot;&gt;Tablename&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid gray;&quot;&gt;PK&lt;/td&gt;&lt;td style=&quot;border:1px solid gray;&quot;&gt;uniqueId&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid gray;&quot;&gt;FK1&lt;/td&gt;&lt;td style=&quot;border:1px solid gray;&quot;&gt;foreignKey&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&quot;border:1px solid gray;&quot;&gt;&lt;/td&gt;&lt;td style=&quot;border:1px solid gray;&quot;&gt;fieldname&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;";

	//String tablexmls = "<table/>";
	String stylexml = "verticalAlign=top;align=left;overflow=fill;html=1;collapsible=1";

	public HelloWorld() {
		try {
//			tablexml = GraphXMLHandler.readXML();
//			tablexml = "&lt;div style=&quot;box-sizing: border-box ; width: 100% ; background: #e4e4e4 ; padding: 2px&quot;&gt;Tablename&lt;/div&gt;&lt;table style=&quot;width: 100% ; font-size: 1em&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;PK&lt;/td&gt;&lt;td style=&quot;padding: 2px&quot;&gt;uniqueId&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;FK1&lt;/td&gt;&lt;td style=&quot;padding: 2px&quot;&gt;foreignKey&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td style=&quot;padding: 2px&quot;&gt;fieldname&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;";
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		mxGraph graph = new mxGraph();
		TableEntity te = new TableEntity();
		te.setTableCaption("新时代的");
		te.setTableName("Act_student");
		List<Column> cols = new ArrayList<Column>();
		Column col1  = new Column();
		col1.setCaption("ID");
		col1.setPrimayKey(true);
		col1.setDesc("唯一标识");
		Column col2  = new Column();
		col2.setCaption("CAPTION");
		col2.setCaptionKey(true);
		col2.setDesc("这是名字");
		Column col3  = new Column();
		col3.setCaption("AGE");
		col3.setDesc("这是年纪");
		cols.add(col1);
		cols.add(col2);
		cols.add(col3);
		te.setColumns(cols);
		DrawTable.drawTable(te, graph);
		
		mxCell parent = (mxCell) graph.getDefaultParent();
		mxIGraphModel model = graph.getModel();
		model.beginUpdate();
		int tablenum = 0;
		int edgenum = 0;
		List<mxCell> arrs = new ArrayList<mxCell>();
		List<mxCell> list = new ArrayList<mxCell>();
		List<mxCell> edges = new ArrayList<mxCell>();
		try {
			mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER);
			geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS));
			geo2.setRelative(true);
			for (int i = 0; i < edgenum; i++) {
//				DefaultEdge edge = new DefaultEdge();
				int num1 = getRandom(0, 20);
				int num2 = getRandom(0, 20);
				//mxCell mxCell1 = list.get(num1);
				mxCell port1 = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter");
				//				graph.addCell(port1, mxCell1);
				mxCell port2 = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter");
				// mxCell2 = list.get(num2);
				//				 graph.addCell(port2, mxCell2);
				Object insertEdge = graph.insertEdge(parent, null, null, null, null);
				mxCell edge1 = (mxCell) insertEdge;
//				edge1.setStyle("curved=1;endArrow=classic;html=1;");
				edge1.setStyle("edgeStyle=orthogonalEdgeStyle");
				edges.add(edge1);
			}
						for(int i = 0;i<tablenum;i++){//创建表的
			Object v1 = graph.insertVertex(parent, null, "12", 100, 100, 200, 180);
			mxCell cell1 = (mxCell) v1;
			cell1.setValue(tablexml);
			cell1.setStyle(stylexml);
			mxGeometry geometry = cell1.getGeometry();
			if(geometry == null)
				geometry = new mxGeometry();
				mxRectangle rect = new mxRectangle();
				rect.setHeight(40);
				rect.setWidth(200);
				geometry.setAlternateBounds(rect);
				
			list.add(cell1);
						}
			for (mxCell edge : edges) {
				mxCell source = list.get(getRandom(0, list.size()));
				mxCell target = list.get(getRandom(0, list.size()));
				edge.setSource(source);
				edge.setTarget(target);
			}
			//		List<mxCell> removes = new ArrayList<mxCell>();
			//		for(int j =0,len = list.size();j<len;j++){
			//			mxCell mxCell = list.get(j);
			//			if(!arrs.contains(mxCell)){
			////				System.out.println(mxCell);
			//				removes.add(mxCell);
			//			}
			////			mxGeometry mx = new mxGeometry();
			////			mx.setHeight(180);
			////			mx.setWidth(200);
			////			System.out.println(mx.contains(150, 140));
			////			System.out.println(mxCell);
			////			mxCell.setGeometry(mx);
			////			System.out.println(mxCell.getEdgeCount());
			////			System.out.println(mxCell.getGeometry());
			//	}
			//		graph.removeCells(removes.toArray(), false);
		} finally {
			graph.getModel().endUpdate();
		}

		mxGraphComponent graphComponent = new mxGraphComponent(graph);
//		getContentPane().add(graphComponent);
				autoLayout(graphComponent);
		mxCodec codec = new mxCodec();
		model.beginUpdate();
		try {
//			graph.removeCells(edges.toArray(), false);
			for (mxCell e : list) {
				int c = e.getChildCount();
				for (int i = 0; i < c; i++) {
					e.remove(i);
				}
			}
//			compareST(list.get(1), list.get(0), graph);
			//			for(mxCell edge: edges){
			//			}
		} finally {
			graph.getModel().endUpdate();
		}

		try {
			for (int j = 0, len = list.size(); j < len; j++) {
				mxCell mxCell = list.get(j);
			}
			xml = mxXmlUtils.getXml(codec.encode(graph.getModel()));
			xml = xml.replaceAll("noEdgeStyle=1", "");
			System.out.println(xml);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void compareST(mxCell source, mxCell target, mxGraph graph) {
		mxGeometry sgeo = source.getGeometry();
		double sx = sgeo.getCenterX();
		double sy = sgeo.getCenterY();
		double sHeight = sgeo.getHeight();
		double sWidth = sgeo.getWidth();
		mxGeometry tgeo = target.getGeometry();
		double tx = tgeo.getCenterX();
		double ty = tgeo.getCenterY();
		double tHeight = tgeo.getWidth();
		double tWidth = tgeo.getWidth();
		double childCount = 0;
		double sportx = 0, tportx = 0;
		double sporty = 0, tporty = 0;
		int schildCount = source.getChildCount();
		int tchildConut = target.getChildCount();
		childCount = Math.max(schildCount, tchildConut);
		if (sx == tx) {
			if (sy > (ty + tHeight)) {
				sportx = getPositionX(childCount,sWidth);
				sporty = 0;
				tportx = getPositionX(childCount,tWidth);
				tporty = tHeight;
			}
			if ((sy + sHeight) < ty) {
				sportx = getPositionX(childCount,sWidth);
				sporty = sHeight;
				tportx = getPositionX(childCount,tWidth);
				tporty = 0;
			}
		} else {
			if ((sx) < tx) {
			}
		}

		mxGeometry spgeo = new mxGeometry(sportx, sporty, 0, 0);
		mxCell sport = new mxCell(null, spgeo, "shape=ellipse;perimter=ellipsePerimeter");
		graph.addCell(sport, source);
		mxGeometry tpgeo = new mxGeometry(tportx, tporty, 0, 0);
		mxCell tport = new mxCell(null, tpgeo, "shape=ellipse;perimter=ellipsePerimeter");
		graph.addCell(tport, target);
		Object insertEdge = graph.insertEdge(graph.getDefaultParent(), null, null, null, null);
		mxCell edge1 = (mxCell) insertEdge;
		edge1.setSource(sport);
		edge1.setTarget(tport);
	}

	private int[] getXY(int width, int height, int childCount) {
		int length = childCount * 5;
		int[] arr = new int[2];
		if (length <= width) {
			arr[0] = length;
			arr[1] = 0;
		} else if (length <= (width + height)) {
			arr[0] = width;
			arr[1] = length - width;
		} else if (length <= (height + width * 2)) {
			arr[0] = length - width - height;
			arr[1] = height;
		} else if (length <= (height * 2 + width * 2)) {
			arr[0] = 0;
			arr[1] = length - height - width * 2;
		}
		return arr;
	}

	public static void main(String[] args) {
		HelloWorld frame = new HelloWorld();
//		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//		frame.setSize(400, 320);
//		frame.setVisible(true);
	}

	private void autoLayout(mxGraphComponent graphComponent) {
		final mxGraph graph = graphComponent.getGraph();
		final mxIGraphLayout layout = getLayout("organicLayout", graphComponent);
		Object cell = graph.getSelectionCell();

		if (cell == null || graph.getModel().getChildCount(cell) == 0) {
			cell = graph.getDefaultParent();
		}

		graph.getModel().beginUpdate();
		try {
			long t0 = System.currentTimeMillis();
			layout.execute(cell);
			System.out.println(("Layout: " + (System.currentTimeMillis() - t0) + " ms"));
		} finally {
			mxMorphing morph = new mxMorphing(graphComponent, 20, 1.2, 20);

			morph.addListener(mxEvent.DONE, new mxIEventListener() {

				public void invoke(Object sender, mxEventObject evt) {
					graph.getModel().endUpdate();
				}

			});

			morph.startAnimation();
		}

	}

	public static int getRandom(int m, int n) {//不包括n
		return (int) (Math.random() * (n - m)) + m;
	}

	/**  
	 * 获取xml  
	 * @return xml xml  
	 */
	public String getXml() {
		return xml;
	}

	/**  
	 * 设置xml  
	 * @param xml xml  
	 */
	public void setXml(String xml) {
		this.xml = xml;
	}

	private mxIGraphLayout getLayout(String ident, final mxGraphComponent graphComponent) {

		mxIGraphLayout layout = null;

		if (ident != null) {
			mxGraph graph = graphComponent.getGraph();

			if (ident.equals("verticalHierarchical")) {
				layout = new mxHierarchicalLayout(graph);
			} else if (ident.equals("horizontalHierarchical")) {
				layout = new mxHierarchicalLayout(graph, JLabel.WEST);
			} else if (ident.equals("verticalTree")) {
				layout = new mxCompactTreeLayout(graph, false);
			} else if (ident.equals("horizontalTree")) {
				layout = new mxCompactTreeLayout(graph, true);
			} else if (ident.equals("parallelEdges")) {
				layout = new mxParallelEdgeLayout(graph);
			} else if (ident.equals("placeEdgeLabels")) {
				layout = new mxEdgeLabelLayout(graph);
			} else if (ident.equals("organicLayout")) {
				layout = new mxOrganicLayout(graph);
			}
			if (ident.equals("verticalPartition")) {
				layout = new mxPartitionLayout(graph, false) {
					/**
					 * Overrides the empty implementation to return the size of the
					 * graph control.
					 */
					public mxRectangle getContainerSize() {
						return graphComponent.getLayoutAreaSize();
					}
				};
			} else if (ident.equals("horizontalPartition")) {
				layout = new mxPartitionLayout(graph, true) {
					/**
					 * Overrides the empty implementation to return the size of the
					 * graph control.
					 */
					public mxRectangle getContainerSize() {
						return graphComponent.getLayoutAreaSize();
					}
				};
			} else if (ident.equals("verticalStack")) {
				layout = new mxStackLayout(graph, false) {
					/**
					 * Overrides the empty implementation to return the size of the
					 * graph control.
					 */
					public mxRectangle getContainerSize() {
						return graphComponent.getLayoutAreaSize();
					}
				};
			} else if (ident.equals("horizontalStack")) {
				layout = new mxStackLayout(graph, true) {
					/**
					 * Overrides the empty implementation to return the size of the
					 * graph control.
					 */
					public mxRectangle getContainerSize() {
						return graphComponent.getLayoutAreaSize();
					}
				};
			} else if (ident.equals("circleLayout")) {
				layout = new mxCircleLayout(graph);
			} else if (ident.equals("fastOrganicLayout")) {
				return new mxFastOrganicLayout(graph);
			}
		}

		return layout;
	}
	
	private double getPositionX (double childCount,double sWidth){
		double x = 0;
		childCount = childCount/2;
		if(childCount % 2 ==0){
			x = sWidth/2 + childCount * lineGap;
		}else{
			x = sWidth/2 - childCount * lineGap;
		}
		return x;
	}
}
